package com.region.http.client.core;

import com.region.common.adapter.logging.LoggerAdapter;
import com.region.common.adapter.logging.LoggerAdapterFactory;
import com.region.http.client.protector.RequestProtector;
import com.region.http.client.request.HttpExecutor;
import com.region.http.client.request.apcache.ApachePoolHttpClientExecutor;
import com.region.http.client.request.apcache.ApacheSingleHttpClientExecutor;
import com.region.http.client.request.simple.SimpleHttpExecutor;
import com.region.plugin.InterceptorProxyManager;
import com.region.plugin.proxy.ProxyHandler;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liujieyu
 * @date 2024/8/20 19:31
 * @desciption
 */
public final class Registers {

    private final LoggerAdapter loggerAdapter = LoggerAdapterFactory.getLogger(getClass());

    private static Registers registers;

    protected static Registers getInstance() {
        return registers;
    }

    protected static Registers getInstance(InterceptorProxyManager interceptorProxyManager) {
        synchronized (Registers.class) {
            if (registers == null) {
                registers = new Registers(interceptorProxyManager);
            }
        }
        return registers;
    }

    private Registers(InterceptorProxyManager interceptorProxyManager) {
        this.interceptorProxyManager = interceptorProxyManager;
        registerHttpExecutor(new SimpleHttpExecutor());
        try {
            Class.forName("org.apache.http.client.HttpClient");
            registerHttpExecutor(new ApacheSingleHttpClientExecutor());
            registerHttpExecutor(new ApachePoolHttpClientExecutor());
        } catch (Exception e) {
            loggerAdapter.warn("Not found apache http client. The error message:" + e.getMessage());
        }
    }

    private Map<Class<? extends HttpExecutor>, HttpExecutor> executors = new ConcurrentHashMap<>();

    private Map<Class<? extends RequestProtector>, RequestProtector> protectors = new ConcurrentHashMap<>();

    private final InterceptorProxyManager interceptorProxyManager;

    public void setProxyType(Class<? extends ProxyHandler> clazz) {
        this.interceptorProxyManager.setProxyTarget(clazz);
    }

    protected void registerHttpExecutor(HttpExecutor executor) {
        executors.putIfAbsent(executor.getClass(), (HttpExecutor) interceptorProxyManager.doInterceptor(executor));
    }

    protected boolean existsHttpExecutor(Class<? extends HttpExecutor> clazz) {
        return executors.containsKey(clazz);
    }

    protected HttpExecutor getHttpExecutor(Class<? extends HttpExecutor> clazz) {
        return executors.get(clazz);
    }

    protected void registerProtector(RequestProtector protector) {
        protectors.putIfAbsent(protector.getClass(), protector);
    }

    protected boolean existsProtector(RequestProtector protector) {
        return protectors.containsKey(protector.getClass());
    }

    protected boolean existsProtector(Class<? extends RequestProtector> clazz) {
        return protectors.containsKey(clazz);
    }

    protected boolean isProtectorEmpty() {
        return protectors.isEmpty();
    }

    protected RequestProtector getProtector(Class<? extends RequestProtector> clazz) {
        return protectors.get(clazz);
    }
}
